const express = require("express");

const app = express();

const cors = require("cors");

const bd = require("body-parser");

// 用于将数据转换为token，编码
const jsonwebtoken = require("jsonwebtoken");

// 用于将tokon还原成数据，解码
const {expressjwt:express_jwt} = require('express-jwt');

// 设置解析post请求中body的数据
app.use(bd.urlencoded({ extended: false }));

// 解决跨域
app.use(cors());

// 1.定义密钥，建议将名字定义成secretKey，可以用来对传输的数据的加密和解密
const secretKey = "JaceZhou&AggieHu ^_^";

/**
 * 3.2 将 JWT字符串 还原成 JSON对象，即配置一个还原的中间件
 *     unless用来指定哪些接口不需要访问权限，这里是指除了带api的其他都需要 还原
 *     因为一般带api的都是公共接口，是可以直接访问的，不需要认证
 *     这里path里面是正则表达式：最外面两个//是正则的标志
 *                         然后两个\/是为了/的转义，因为有/api/
 *                         ^是指只要有api的所有都要匹配
 * */ 
app.use(express_jwt({ secret: secretKey,algorithms: ["HS256"] }).unless({ path: [/^\/api\//] }));

// 2.使用api接口login用于用户的登录
app.post("/api/login", (req, res) => {
  const userinfo = req.body;

  if (userinfo.username !== "admin" || userinfo.password !== "000000") {
    return res.send({
      status: 400,
      msg: "登陆失败",
    });
  }

  // 2.1注意不要将密码放入token加密字符串中，在传输过程中太危险
  const tokenStr = jsonwebtoken.sign(
    { username: userinfo.username },
    secretKey,
    { expiresIn: "30s" }
  );

  // 2.2登陆成功后用jwt的sign生成JWT字符串，然后通过token属性发给客户端
  res.send({
    status: 200,
    msg: "登陆成功",
    /**
     * 参数一：用户的信息对象，这里根据名字做token就行了
     * 参数二：密钥
     * 参数三：token验证的有效期
     */
    token: tokenStr,
  });
});

// 3.使用以下接口来获取用户信息
app.get("/admin/getinfo", (req, res) => {
  /**
   * 3.1一旦服务器端注册了express-jwt中间件，就会自动将解析出来的用户数据挂载到req.auth
   * 可以这么理解：既然注册了这个中间件，就说明有需要解析的JWT字符串，那么直接放到公共的req对象里
   * 各个用户到req里面取就行了
   * */ 
  console.log(req.auth);

  res.send({
    status: 200,
    msg: "获取用户信息成功！",
    data: req.auth,
  });
});

/**
 * 4.全局使用错误处理中间件，来捕获解析JWT失败后产生的错误
 *   使用错误中间件可以防止程序崩溃，相当于catch到了
 * */ 
app.use((err,req,res,next)=>{
  // token过期或不合法导致的错误
   if(err.name === 'UnauthorizedError'){
      return res.send({
         status:401,
         message:'无效的token！'
      })
   }
  //  其他原因导致的错误
  res.send({
     status:500,
     message:'其他错误！'
  })
})

app.listen("8080", () => {
  console.log("http://127.0.0.1:8080");
});
